﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Xml.Serialization;
using Ionic.Zip;
using System.Reflection;

namespace Packager
{
    public partial class frmPackager : Form
    {
        private string lastFilename = string.Empty;
        private TreeNode currentNode = null;

        public frmPackager()
        {
            InitializeComponent();
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            if (fbdRoot.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                txtRoot.Text = fbdRoot.SelectedPath;

            btnLoad.Enabled = !string.IsNullOrEmpty(txtRoot.Text);
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            trvSource.Nodes.Clear();
            trvDest.Nodes.Clear();
            trvDest.Nodes.Add("Application folder");
            LoadFolders(txtRoot.Text, null);
        }

        private void LoadFolders(string folderRoot, TreeNode nodeRoot)
        {
            TreeNode curNode = nodeRoot == null
                        ? trvSource.Nodes.Add(Path.GetFileName(folderRoot))
                        : nodeRoot.Nodes.Add(Path.GetFileName(folderRoot));

            curNode.Tag = folderRoot;

            foreach (string dir in Directory.GetDirectories(folderRoot))
                LoadFolders(dir, curNode);

            foreach (string file in Directory.GetFiles(folderRoot))
            {
                TreeNode fileNode = curNode.Nodes.Add(Path.GetFileName(file));
                fileNode.Tag = file;
            }
        }

        private void trvSource_ItemDrag(object sender, ItemDragEventArgs e)
        {
            DoDragDrop(e.Item, DragDropEffects.Copy);
        }

        private void trvDest_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Copy;
        }

        private void trvDest_DragDrop(object sender, DragEventArgs e)
        {
            TreeNode NewNode;

            if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false))
            {
                Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
                TreeNode DestinationNode = ((TreeView)sender).GetNodeAt(pt);
                NewNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
                if (DestinationNode == null)
                {
                    trvDest.Nodes[0].Nodes.Add((TreeNode)NewNode.Clone());
                    trvDest.Nodes[0].Expand();
                }
                else if (DestinationNode.TreeView != NewNode.TreeView)
                {
                    DestinationNode.Nodes.Add((TreeNode)NewNode.Clone());
                    DestinationNode.Expand();
                    //Remove Original Node
                    //NewNode.Remove();
                }
            }
        }

        private void trvDest_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete && trvDest.SelectedNode != null &&
                trvDest.SelectedNode.Text != "Application folder")
                trvDest.SelectedNode.Remove();
        }
        private void tsmNew_Click(object sender, EventArgs e)
        {
            txtRoot.Text = string.Empty;
            trvSource.Nodes.Clear();
            trvDest.Nodes.Clear();
        }

        private void tsmLoad_Click(object sender, EventArgs e)
        {
            if (ofdLoad.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                LoadData(ofdLoad.FileName);
        }

        private void tsmSave_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(lastFilename))
                SaveData(lastFilename);
            else
                tsmSaveAs_Click(sender, e);
        }

        private void tsmSaveAs_Click(object sender, EventArgs e)
        {
            if (sfdSave.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                SaveData(sfdSave.FileName);
        }

        private void tsmPublish_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            string filename = string.Concat(txtApplication.Text, "_", txtVersion.Text);
            string zipfilename = string.Concat(filename, ".zip");
            string infoFilename = Path.ChangeExtension(txtApplication.Text, ".inf");
            FtpUploader.UploadFile(txtApplication.Text, zipfilename);
            FtpUploader.UploadFile(txtApplication.Text, infoFilename);
            this.Cursor = Cursors.Default;
        }

        private void tsmExit_Click(object sender, EventArgs e)
        {
            Application.ExitThread();
        }

        private void LoadData(string filename)
        {
            lastFilename = filename;
            XmlSerializer xSer = new XmlSerializer(typeof(SaveData));
            using (TextReader reader = new StreamReader(filename))
            {
                SaveData sData = (SaveData)xSer.Deserialize(reader);
                txtApplication.Text = sData.ApplicationName;
                txtVersion.Text = sData.Version;

                txtRoot.Text = sData.Structure.Path;
                trvSource.Nodes.Clear();
                trvDest.Nodes.Clear();
                LoadFolders(txtRoot.Text, null);
                CreateTreeFromStructure(trvDest.Nodes, sData.Structure);
            }
        }

        private void SaveData(string filename)
        {
            lastFilename = filename;
            SaveData sData = new SaveData();
            sData.ApplicationName = txtApplication.Text;
            sData.Version = txtVersion.Text;
            sData.Structure.Text = "Root";
            sData.Structure.Path = txtRoot.Text;
            CreateStructureFromTree(trvDest.Nodes, sData.Structure);
            XmlSerializer xSer = new XmlSerializer(typeof(SaveData));
            using (TextWriter writer = new StreamWriter(filename))
            {
                xSer.Serialize(writer, sData);
                writer.Close();
            }
        }

        private void CreateStructureFromTree(TreeNodeCollection nodes, SingleField sf)
        {
            foreach (TreeNode node in nodes)
            {
                SingleField cur = new SingleField();
                cur.Text = node.Text;
                cur.Path = node.Tag == null ? string.Empty : node.Tag.ToString();
                sf.Nodes.Add(cur);
                if (node.Nodes.Count > 0)
                    CreateStructureFromTree(node.Nodes, cur);
            }
        }

        private void CreateTreeFromStructure(TreeNodeCollection nodes, SingleField sf)
        {
            foreach (SingleField cur in sf.Nodes)
            {
                TreeNode node = new TreeNode(cur.Text);
                node.Tag = cur.Path;
                nodes.Add(node);
                if (cur.Nodes.Count > 0)
                    CreateTreeFromStructure(node.Nodes, cur);
            }
        }

        private void tsmCreate_Click(object sender, EventArgs e)
        {
            string filename = string.Concat(txtApplication.Text, "_", txtVersion.Text);
            string zipfilename = string.Concat(filename, ".zip");
            string infoFilename = Path.ChangeExtension(txtApplication.Text, ".inf");
            if (File.Exists(zipfilename))
                File.Delete(zipfilename);
            using (ZipFile zipfile = new ZipFile(zipfilename))
            {
                CreateZipFromTree(trvDest.Nodes, zipfile);
                zipfile.Save();
            }

            InfoData infoData = new InfoData();
            infoData.Version = txtVersion.Text;
            infoData.Filename = zipfilename;

            XmlSerializer xSer = new XmlSerializer(typeof(InfoData));
            using (TextWriter writer = new StreamWriter(infoFilename))
            {
                xSer.Serialize(writer, infoData);
                writer.Close();
            }
        }

        private void CreateZipFromTree(TreeNodeCollection nodes, ZipFile zip)
        {
            foreach (TreeNode node in nodes)
            {
                if (node.Tag!= null && File.Exists(node.Tag.ToString()))
                {
                    string folder = Path.GetDirectoryName(node.Tag.ToString().Substring(txtRoot.Text.Length));
                    zip.AddFile(node.Tag.ToString(), folder);
                }
                if (node.Nodes.Count > 0)
                    CreateZipFromTree(node.Nodes, zip);
            }
        }

        private void tsmiGetVersion_Click(object sender, EventArgs e)
        {
            string path = Path.Combine(txtRoot.Text, currentNode.Text);
            txtVersion.Text = Assembly.LoadFile(path).GetName().Version.ToString(3);
        }

        private void trvSource_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                Point pt = new Point(e.X, e.Y);
                trvSource.PointToClient(pt);

                currentNode = trvSource.GetNodeAt(pt);

            }
        }

    }
}
